package com.lechi.web.service.impl;


import com.alibaba.fastjson2.JSON;
import com.lechi.iot.netty.utils.BytesToHexUtil;
import com.lechi.iot.netty.utils.ModbusCrc16Utils;
import com.lechi.web.constants.Constants;
import com.lechi.web.dto.IotDeviceCmdCreateDto;
import com.lechi.web.service.IIotGenCmdAndCacheAndScheduleService;
import com.lechi.web.system.domain.IotDeviceCmdBo;
import com.lechi.web.system.domain.IotDeviceCmdParse;
import com.lechi.web.system.mapper.iot.IotDeviceCmdMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * The type Iot gen cmd and cache and schedule service.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IotGenCmdAndCacheAndScheduleServiceImpl implements IIotGenCmdAndCacheAndScheduleService {

    private final IotDeviceCmdMapper iotDeviceCmdMapper;

    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public void genCmdAndUpdateCmd(Long deviceId) {
        List<IotDeviceCmdParse> iotDeviceCmdCreates = iotDeviceCmdMapper.selectIotDeviceCmdListForCreate(deviceId); // 查询所有的指令配置 根据从站号，功能码
        List<IotDeviceCmdParse> iotDeviceCmdCreateList = iotDeviceCmdMapper.selectIotDeviceCmdListByOrder(deviceId);
        for (IotDeviceCmdParse iotDeviceCmdCreate : iotDeviceCmdCreates) {
            IotDeviceCmdCreateDto iotDeviceCmdCreateDto = new IotDeviceCmdCreateDto();
            BeanUtils.copyProperties(iotDeviceCmdCreate, iotDeviceCmdCreateDto);
            for (IotDeviceCmdParse iotDeviceCmdBo : iotDeviceCmdCreateList) {
                if (iotDeviceCmdCreate.getStationAddr().equals(iotDeviceCmdBo.getStationAddr())) {
                    if (iotDeviceCmdCreateDto.getMinOffsetCode() > iotDeviceCmdBo.getOffsetCode()) {
                        iotDeviceCmdCreateDto.setMinOffsetCode(iotDeviceCmdBo.getOffsetCode());
                    }
                    if (iotDeviceCmdCreateDto.getMaxOffsetCode() < iotDeviceCmdBo.getOffsetCode()) {
                        iotDeviceCmdCreateDto.setMaxOffsetCode(iotDeviceCmdBo.getOffsetCode());
                        iotDeviceCmdCreateDto.setDataFormat(iotDeviceCmdBo.getDataFormat());
                    }
                }
            }
            Map<String, Integer> map = new HashMap<>();
            if (Constants.FLOAT_FORMAT_32.equals(iotDeviceCmdCreateDto.getDataFormat()) || Constants.INTEGER_DATA_FORMAT_32.equals(iotDeviceCmdCreateDto.getDataFormat())) {
                map.put(iotDeviceCmdCreate.getDeviceId() + "_register_" + iotDeviceCmdCreate.getStationAddr(), iotDeviceCmdCreateDto.getMaxOffsetCode() - iotDeviceCmdCreateDto.getMinOffsetCode() + 2);
            } else if (Constants.FLOAT_FORMAT_16.equals(iotDeviceCmdCreateDto.getDataFormat()) || Constants.INTEGER_DATA_FORMAT_16.equals(iotDeviceCmdCreateDto.getDataFormat())) {
                map.put(iotDeviceCmdCreate.getDeviceId() + "_register_" + iotDeviceCmdCreate.getStationAddr(), iotDeviceCmdCreateDto.getMaxOffsetCode() - iotDeviceCmdCreateDto.getMinOffsetCode() + 1);
            }
            map.put(iotDeviceCmdCreate.getDeviceId() + "_beginBit_" + iotDeviceCmdCreate.getStationAddr(), iotDeviceCmdCreateDto.getMinOffsetCode() - 1);

            iotDeviceCmdCreateList.forEach(iotDeviceCmd -> {
                if (iotDeviceCmd.getStationAddr().equals(iotDeviceCmdCreateDto.getStationAddr())) {
                    Integer register = map.get(iotDeviceCmdCreate.getDeviceId() + "_register_" + iotDeviceCmdCreate.getStationAddr());
                    String registerStr = register < 16 ? "000" + Integer.toHexString(register) : "00" + Integer.toHexString(register);
                    Integer beginBit_ = map.get(iotDeviceCmdCreate.getDeviceId() + "_beginBit_" + iotDeviceCmdCreate.getStationAddr());
                    String beginBitStr = beginBit_ < 16 ? "000" + Integer.toHexString(beginBit_) : "00" + Integer.toHexString(beginBit_);
                    String cmd = iotDeviceCmdCreateDto.getStationAddr() + iotDeviceCmd.getFunctionCode() + beginBitStr + registerStr;
                    byte[] arr = BytesToHexUtil.hexStrToBinaryStr(cmd);
                    if (arr == null) {
                        log.error("生成的指令为空,规则内容: {}, 原始指令数据：{}", JSON.toJSON(iotDeviceCmdCreateDto), JSON.toJSON(iotDeviceCmd));
                        return;
                    }
                    IotDeviceCmdBo iotDeviceCmdBo = new IotDeviceCmdBo();
                    iotDeviceCmdBo.setId(iotDeviceCmd.getId());
                    iotDeviceCmdBo.setCmd(cmd + ModbusCrc16Utils.getCrcString(arr));
                    log.error("{}生成的指令为空iotDeviceCmdBo.getCmd(){}", iotDeviceCmdBo.getId(), iotDeviceCmdBo.getCmd());
                    iotDeviceCmdMapper.updateIotDeviceCmd(iotDeviceCmdBo);
                }
            });
        }
    }
}
